package com.sau.pixelcart.service.impl;

import cn.hutool.db.sql.Order;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sau.pixelcart.common.constant.OrderConstant;
import com.sau.pixelcart.common.context.UserContext;
import com.sau.pixelcart.common.exception.BusinessException;
import com.sau.pixelcart.common.result.PageResult;
import com.sau.pixelcart.domain.dto.OrderDTO;
import com.sau.pixelcart.domain.dto.OrderPageDTO;
import com.sau.pixelcart.domain.dto.ProductDTO;
import com.sau.pixelcart.domain.dto.SalesAnalysisDTO;
import com.sau.pixelcart.domain.entity.*;
import com.sau.pixelcart.domain.vo.*;
import com.sau.pixelcart.mapper.*;
import com.sau.pixelcart.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.hutool.core.util.NumberUtil.add;

/**
 * <p>
 * 订单核心信息（日均百万级数据需考虑分表） 服务实现类
 * </p>
 *
 * @author Inton
 * @since 2025-03-27
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersService {

    @Autowired
    private PublicMethodService publicMethodService;

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private IOrderDetailService orderDetailService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IProductInventoryService productInventoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IProductService productService;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private IInventoryAdjustmentService inventoryAdjustmentService;

    @Autowired
    private IInventoryAlertService inventoryAlertService;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductInventoryServiceImpl productInventoryServiceImpl;

    @Autowired
    private ProductInventoryMapper productInventoryMapper;

    /**
     * 订单分页查询
     * @param orderPageDTO
     * @return
     */
    @Override
    public PageResult<OrderVO> pageQuery(OrderPageDTO orderPageDTO) {
        //开始分页
        Page<Orders> page = new Page<>(orderPageDTO.getPage(), orderPageDTO.getPageSize());

        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        if(orderPageDTO.getKeyword() != null && !orderPageDTO.getKeyword().equals("")){
            queryWrapper.like(Orders::getCode,orderPageDTO.getKeyword());
        }
        if(orderPageDTO.getMonth() != null && !orderPageDTO.getMonth().equals("")){
            LocalDate beginDate = publicMethodService.getBeginDate(orderPageDTO.getMonth());
            LocalDate endDate = publicMethodService.getEndDate(orderPageDTO.getMonth());

            //设置条件为本月的数据
            queryWrapper.between(Orders::getCreateTime,beginDate,endDate);
        }

        if(orderPageDTO.getStatus() != null && !orderPageDTO.getStatus().equals("")){
            queryWrapper.eq(Orders::getStatus,orderPageDTO.getStatus());
        }

        queryWrapper.orderByDesc(Orders::getCreateTime);
        Page<Orders> ordersPage = ordersMapper.selectPage(page, queryWrapper);


        List<OrderVO> orderVOList = ordersPage.getRecords().stream().map(order -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            orderVO.setOperatorName(userMapper.selectById(order.getOperatorId()).getUsername());
            return orderVO;
        }).collect(Collectors.toList());

        PageResult<OrderVO> pageResult = new PageResult<>();
        pageResult.setTotal(ordersPage.getTotal());
        pageResult.setRecords(orderVOList);

        return pageResult;
    }

    /**
     * 创建订单
     * @param orderDTO
     */
    @Override
    @Transactional
    public void saveOrder(OrderDTO orderDTO) {

        Orders orders = new Orders();
        //订单编号code生成规则："#" + "随机6位数字" + "年月日时分秒"
        //随机生成6位数字
        int randomNumber = ThreadLocalRandom.current().nextInt(100000, 1000000);
        String randomPart = String.valueOf(randomNumber);

        //生成当前日期
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String datePart = dtf.format(LocalDateTime.now());

        String code = "#" + randomPart + datePart;
        orders.setCode(code);

        //结算总金额price和总商品数量
        BigDecimal price = new BigDecimal(0);
        int totalNumber = 0;
        List<ProductDTO> productList = orderDTO.getProductList();
        for (ProductDTO product : productList) {
            if((product.getPrice() != null && product.getPrice().compareTo(BigDecimal.ZERO) != 0) && product.getStock() != null){
                int number = product.getStock();
                BigDecimal onePrice = product.getPrice();
                BigDecimal productPrice = onePrice.multiply(new BigDecimal(number));
                price = price.add(productPrice);
                totalNumber += number;
            }
        }
        orders.setPrice(price);
        orders.setTotalNumber(totalNumber);

        //创建时间createTime
        orders.setCreateTime(LocalDateTime.now());
        //操作者operatorId
        orders.setOperatorId(UserContext.getUser());
        //订单状态status
        if(orderDTO.getPayCode() == null){
            //稍后支付
            orders.setStatus(OrderConstant.STATUS_PENDING);
        }else{
            orders.setStatus(OrderConstant.STATUS_COMPLETED);
        }

        //生成订单信息到orders表
        ordersMapper.insert(orders);

        //将list信息添加到order_detail表
        List<OrderDetail> orderDetailList = orderDTO.getProductList().stream().map(product -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orders.getId());
            orderDetail.setProductId(product.getId());
            orderDetail.setProductName(product.getName());
            orderDetail.setNumber(product.getStock());
            orderDetail.setUnitPrice(product.getPrice());
            return orderDetail;
        }).collect(Collectors.toList());

        //保存订单详情
        orderDetailService.saveBatch(orderDetailList);


        if(orderDTO.getPayCode() != null){
            //执行出库操作（分布式锁）
            productInventoryService.outStock(orderDTO.getProductList());
            //清除redis缓存
            String key = "product_*";
            Set keys = redisTemplate.keys(key);
            redisTemplate.delete(keys);
        }

    }

    /**
     * 处理未支付订单
     * @param orderDTO
     */
    @Transactional
    public void solveNoPayOrder(OrderDTO orderDTO) {
        String orderId = orderDTO.getId();

        //根据订单id查订单详情中的商品列表
        List<ProductDTO> productList = orderDetailService.getByOrdersId(orderId).stream()
                .map(orderDetail -> {
                    String productId = orderDetail.getProductId();
                    Product product = productMapper.selectById(productId);
                    ProductDTO productDTO = new ProductDTO();
                    BeanUtils.copyProperties(product, productDTO);

                    LambdaQueryWrapper<ProductInventory> productInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    productInventoryLambdaQueryWrapper.eq(ProductInventory::getProductId, productId);
                    ProductInventory productInventory = productInventoryMapper.selectOne(productInventoryLambdaQueryWrapper);
                    productDTO.setStock(orderDTO.getTotalNumber());
                    productDTO.setVersion(productInventory.getVersion());
                    return productDTO;
                }).collect(Collectors.toList());

        Orders orders = ordersMapper.selectById(orderDTO.getId());
        orders.setStatus(OrderConstant.STATUS_COMPLETED);
        ordersMapper.updateById(orders);

        //将商品列表出库
        //执行出库操作（分布式锁）
        productInventoryService.outStock(productList);
        //清除redis缓存
        String key = "product_*";
        Set keys = redisTemplate.keys(key);
        redisTemplate.delete(keys);
    }

    /**
     * 处理超时未支付订单
     * @return
     */
    @Override
    public int batchCancelUnpaidOrders() {
        LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();

        //计算时间阈值
        LocalDateTime thresholdTime = LocalDateTime.now().minusMinutes(60);

        ordersLambdaQueryWrapper.eq(Orders::getStatus, OrderConstant.STATUS_PENDING)
                .lt(Orders::getCreateTime, thresholdTime);

        List<Orders> ordersList = ordersMapper.selectList(ordersLambdaQueryWrapper);
        for (Orders orders : ordersList) {
            orders.setStatus(OrderConstant.STATUS_CANCELED);
            ordersMapper.updateById(orders);
        }

        return ordersList.size();
    }

    /**
     * 销售分析
     * @param salesAnalysisDTO
     * @return
     */
    @Override
    public SalesAnalysisVO saleAnalysis(SalesAnalysisDTO salesAnalysisDTO) {

        // 定义日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 设置结束时间为今天
        LocalDate endDate = LocalDate.now().plusDays(1);

        // 设置开始时间为 7 天前
        LocalDate beginDate = endDate.minusDays(7);

        if(salesAnalysisDTO.getBeginDate() != null && salesAnalysisDTO.getEndDate() != null){
            beginDate = salesAnalysisDTO.getBeginDate().plusDays(1);
            endDate = salesAnalysisDTO.getEndDate().plusDays(1);
        }

        LambdaQueryWrapper<Orders> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ge(Orders::getCreateTime,beginDate);
        lambdaQueryWrapper.le(Orders::getCreateTime,endDate);
        List<Orders> orders = ordersMapper.selectList(lambdaQueryWrapper);

        List<SalesTrendVO> salesTrendVOList = getSalesTrendDateList(beginDate, endDate, orders);

        // 4. TODO 转换为最终需要的List结构
        List<CategorySalesVO> categorySalesList = getCategorySales(beginDate,endDate);

        return SalesAnalysisVO.builder()
                .categorySalesList(categorySalesList)
                .saleTrendList(salesTrendVOList)
                .build();
    }

    /**
     * 导出报表
     * @param response
     */
    @Override
    public void exportOrders(HttpServletResponse response) throws IOException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        InputStream inputStream = null;

        try {
            LocalDate beginDate = LocalDate.now().minusDays(29);
            LocalDate endDate = LocalDate.now().plusDays(1);

            //查数据库，获取订单数据
            LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();
            ordersLambdaQueryWrapper.gt(Orders::getCreateTime, beginDate);
            ordersLambdaQueryWrapper.lt(Orders::getCreateTime, endDate);
            ordersLambdaQueryWrapper.eq(Orders::getStatus, OrderConstant.STATUS_COMPLETED);
            //时间段内的订单信息
            List<Orders> orderList = ordersMapper.selectList(ordersLambdaQueryWrapper);

            //基于日期给订单分组
            Map<LocalDate, List<Orders>> orderDateList = orderList
                    .stream().collect(Collectors.groupingBy(orders -> LocalDate.from(orders.getCreateTime())));

            //时间段内的入库信息
            LambdaQueryWrapper<InventoryAdjustment> inventoryAdjustmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
            inventoryAdjustmentLambdaQueryWrapper.eq(InventoryAdjustment::getReason,"inStock");
            inventoryAdjustmentLambdaQueryWrapper.gt(InventoryAdjustment::getAdjustmentTime,beginDate);
            inventoryAdjustmentLambdaQueryWrapper.lt(InventoryAdjustment::getAdjustmentTime,endDate);
            List<InventoryAdjustment> inventoryAdjustmentList = inventoryAdjustmentService.list(inventoryAdjustmentLambdaQueryWrapper);

            //基于日期给入库操作分组
            Map<LocalDate, List<InventoryAdjustment>> inventoryAdjustmentDateList = inventoryAdjustmentList
                    .stream().collect(Collectors.groupingBy(inventoryAdjustment -> LocalDate.from(inventoryAdjustment.getAdjustmentTime())));

            //获取库存预警信息
            LambdaQueryWrapper<InventoryAlert> inventoryAlertLambdaQueryWrapper = new LambdaQueryWrapper<>();
            inventoryAlertLambdaQueryWrapper.gt(InventoryAlert::getTriggerTime,beginDate);
            inventoryAlertLambdaQueryWrapper.lt(InventoryAlert::getTriggerTime,endDate);
            List<InventoryAlert> inventoryAlertList = inventoryAlertService.list(inventoryAlertLambdaQueryWrapper);
            Map<LocalDate, List<InventoryAlert>> inventoryAlertDateMap = inventoryAlertList.stream()
                    .collect(Collectors.groupingBy(inventoryAlert -> LocalDate.from(inventoryAlert.getTriggerTime())));

            //通过获取class对象，获取目录下的模板文件，对其进行写入操作
            inputStream = this.getClass().getClassLoader().getResourceAsStream("template/订单导出模板.xlsx");
            if (inputStream == null) {
                throw new IOException("无法找到Excel模板文件");
            }

            // 使用try-with-resources确保资源正确关闭
            try (XSSFWorkbook excel = new XSSFWorkbook(inputStream);
                 ServletOutputStream outputStream = response.getOutputStream()) {

                //获取sheet1
                XSSFSheet sheet1 = excel.getSheet("Sheet1");
                //获取第二行，批量插入
                LocalDate currentDate = beginDate;

                int i = 1;
                while (currentDate.isBefore(endDate)) {
                    List<Orders> orders = orderDateList.get(currentDate);
                    if (orders == null) {
                        currentDate = currentDate.plusDays(1);
                        continue;
                    }
                    //从第二行开始获取
                    XSSFRow row = sheet1.getRow(i);
                    //日期列
                    if (row == null) {
                        // 如果行不存在，创建新行
                        row = sheet1.createRow(i);
                    }
                    if (row.getCell(0) == null) {
                        // 如果行不存在，创建新行
                        XSSFCell cell1 = row.createCell(0);
                        cell1.setCellValue(formatter.format(currentDate));
                    } else {
                        XSSFCell cell1 = row.getCell(0);
                        cell1.setCellValue(formatter.format(currentDate));
                    }

                    //获取当日所有订单
                    BigDecimal totalAmount = BigDecimal.ZERO;
                    int totalProduct = 0;

                    for (Orders order : orders) {
                        totalAmount = totalAmount.add(order.getPrice());
                        totalProduct += order.getTotalNumber();
                    }
                    //设置当日总营业额
                    if (row.getCell(1) == null) {
                        // 如果单元格不存在，创建新单元格
                        XSSFCell cell2 = row.createCell(1);
                        cell2.setCellValue(totalAmount.doubleValue());
                    } else {
                        XSSFCell cell2 = row.getCell(1);
                        cell2.setCellValue(totalAmount.doubleValue());
                    }

                    //设置订单完成数
                    if (row.getCell(2) == null) {
                        // 如果单元格不存在，创建新单元格
                        XSSFCell cell3 = row.createCell(2);
                        cell3.setCellValue(orders.size());
                    } else {
                        XSSFCell cell3 = row.getCell(2);
                        cell3.setCellValue(orders.size());
                    }

                    //设置售出商品数
                    if (row.getCell(3) == null) {
                        // 如果单元格不存在，创建新单元格
                        XSSFCell cell4 = row.createCell(3);
                        cell4.setCellValue(totalProduct);
                    } else {
                        XSSFCell cell4 = row.getCell(3);
                        cell4.setCellValue(totalProduct);
                    }

                    //获取当日入库数据
                    int totalInStock = 0;
                    List<InventoryAdjustment> inventoryAdjustments = inventoryAdjustmentDateList.get(currentDate);
                    if (inventoryAdjustments == null) {
                        if (row.getCell(4) == null) {
                            // 如果单元格不存在，创建新单元格
                            XSSFCell cell5 = row.createCell(4);
                            cell5.setCellValue(totalInStock);
                        } else {
                            XSSFCell cell5 = row.getCell(4);
                            cell5.setCellValue(totalInStock);
                        }
                    } else {
                        for (InventoryAdjustment inventoryAdjustment : inventoryAdjustments) {
                            totalInStock += inventoryAdjustment.getNewStock() - inventoryAdjustment.getOldStock();
                        }
                        //设置当日总入库数
                        if (row.getCell(4) == null) {
                            // 如果单元格不存在，创建新单元格
                            XSSFCell cell5 = row.createCell(4);
                            cell5.setCellValue(totalInStock);
                        } else {
                            XSSFCell cell5 = row.getCell(4);
                            cell5.setCellValue(totalInStock);
                        }
                    }

                    //设置触发预警数
                    List<InventoryAlert> inventoryAlerts = inventoryAlertDateMap.get(currentDate);
                    if (inventoryAlerts == null) {
                        if (row.getCell(5) == null) {
                            // 如果单元格不存在，创建新单元格
                            XSSFCell cell6 = row.createCell(5);
                            cell6.setCellValue(0);
                        } else {
                            XSSFCell cell6 = row.getCell(5);
                            cell6.setCellValue(0);
                        }
                    } else {
                        if (row.getCell(5) == null) {
                            // 如果单元格不存在，创建新单元格
                            XSSFCell cell6 = row.createCell(5);
                            cell6.setCellValue(inventoryAlerts.size());
                        } else {
                            XSSFCell cell6 = row.getCell(5);
                            cell6.setCellValue(inventoryAlerts.size());
                        }
                    }

                    currentDate = currentDate.plusDays(1);
                    i++;
                }

                // 设置响应头
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                String fileName = URLEncoder.encode("订单导出报表.xlsx", "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName);
                // 添加缓存控制，防止浏览器缓存
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                response.setHeader("Pragma", "no-cache");
                response.setHeader("Expires", "0");

                // 写入并刷新
                excel.write(outputStream);
                outputStream.flush();
            }
        } catch (Exception e) {
            // 记录异常
            log.error("导出Excel文件失败", e);
            // 设置错误响应
            response.reset();
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

            // 使用try-with-resources自动关闭PrintWriter
            try (PrintWriter writer = response.getWriter()) {
                writer.write("{\"code\":500,\"message\":\"导出Excel文件失败: " + e.getMessage() + "\"}");
            }
        } finally {
            // 关闭输入流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭输入流失败", e);
                }
            }
        }
    }

    /**
     * 查询折线图
     * @param beginDate
     * @param endDate
     * @param orders
     * @return
     */
    public List<SalesTrendVO> getSalesTrendDateList(LocalDate beginDate, LocalDate endDate,List<Orders> orders) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        //查折线图
        List<SalesTrendVO> salesTrendVOList = new ArrayList<>();
        for(LocalDate thisDay = beginDate; thisDay.isBefore(endDate); thisDay = thisDay.plusDays(1)){
            //today为当天
            LocalDate today = thisDay;
            List<Orders> oneDayOrders = orders.stream()
                    .filter(order -> {
                        LocalDate createTime = LocalDate.from(order.getCreateTime());
                        return createTime.equals(today) && order.getStatus().equals(OrderConstant.STATUS_COMPLETED);
                    }).collect(Collectors.toList());

            //当天销售额
            BigDecimal saleAmount = oneDayOrders.stream()
                    .map(Orders::getPrice)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);  // 使用reduce累加

            //当天日期（"yyyy-MM-dd"）
            String todayStr = today.format(formatter);

            //当天订单数
            Integer orderCount = oneDayOrders.size();

            SalesTrendVO salesTrendVO = new SalesTrendVO();
            salesTrendVO.setOrderCount(orderCount);
            salesTrendVO.setSaleAmount(saleAmount);
            salesTrendVO.setDate(todayStr);
            salesTrendVOList.add(salesTrendVO);
        }
        return salesTrendVOList;
    }

    /**
     * 查询饼图
     * @param beginDate
     * @param endDate
     * @return
     */
    public List<CategorySalesVO> getCategorySales(LocalDate beginDate, LocalDate endDate){
        //查饼图，七天内的
        LocalDate end = endDate;
        LocalDate begin = beginDate;
        // 1. 查询订单ID列表（7天内）
        List<String> ordersIdList = this.list().stream()
                .filter(order -> {
                    LocalDate createDate = order.getCreateTime().toLocalDate();
                    return !createDate.isBefore(begin)  && !createDate.isAfter(end);
                })
                .map(Orders::getId)
                .collect(Collectors.toList());

        if (ordersIdList.isEmpty())  {
            throw new BusinessException("日期范围内无订单");
        }

        // 2. 查询订单详情列表
        LambdaQueryWrapper<OrderDetail> detailQuery = new LambdaQueryWrapper<>();
        detailQuery.in(OrderDetail::getOrderId,  ordersIdList);
        List<OrderDetail> details = orderDetailService.list(detailQuery);

        // 3. 提取商品ID并去重
        Set<String> productIds = details.stream()
                .map(OrderDetail::getProductId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 4. 批量查询商品及其分类，构建分类名称映射表
        Map<String, String> productCategoryMap = new HashMap<>();
        if (!productIds.isEmpty())  {
            LambdaQueryWrapper<Product> productQuery = new LambdaQueryWrapper<>();
            productQuery.in(Product::getId,  productIds);
            List<Product> products = productService.list(productQuery);

            for (Product product : products) {
                String categoryName = "未分类";
                if (product.getCategoryId()  != null) {
                    Category category = categoryService.getById(product.getCategoryId());
                    if (category != null && category.getName()  != null) {
                        categoryName = category.getName();
                    }
                }
                productCategoryMap.put(product.getId(),  categoryName);
            }
        }

        // 5. 分类统计核心逻辑（混合流与Map合并操作）
        Map<String, CategorySalesVO> resultMap = new HashMap<>();
        for (OrderDetail detail : details) {
            if (detail.getProductId()  == null) continue;

            // 获取分类名称（含空值保护）
            String categoryName = productCategoryMap.getOrDefault(detail.getProductId(),  "未分类");

            // 合并统计结果
            resultMap.compute(categoryName,  (key, existingVo) -> {
                CategorySalesVO vo = (existingVo != null) ? existingVo : new CategorySalesVO();
                vo.setCategoryName(categoryName);

                // 金额累加（处理null值）
                BigDecimal detailAmount = detail.getTotalPrice()  != null ?
                        detail.getTotalPrice()  : BigDecimal.ZERO;
                vo.setTotalAmount(vo.getTotalAmount()  != null ?
                        vo.getTotalAmount().add(detailAmount)  : detailAmount);

                // 数量累加（处理null值）
                Integer detailQty = detail.getNumber()  != null ? detail.getNumber()  : 0;
                vo.setTotalQuantity(vo.getTotalQuantity()  != null ?
                        vo.getTotalQuantity()  + detailQty : detailQty);

                return vo;
            });
        }
        // 4. 转换为最终需要的List结构
        List<CategorySalesVO> categorySalesList = new ArrayList<>(resultMap.values());
        return categorySalesList;
    }

}
